package com.bw;

import com.alibaba.alink.operator.batch.BatchOperator;
import com.alibaba.alink.operator.batch.dataproc.SplitBatchOp;
import com.alibaba.alink.operator.batch.evaluation.EvalMultiClassBatchOp;
import com.alibaba.alink.operator.batch.evaluation.EvalRegressionBatchOp;
import com.alibaba.alink.operator.batch.source.CsvSourceBatchOp;
import com.alibaba.alink.operator.common.evaluation.MultiClassMetrics;
import com.alibaba.alink.operator.common.evaluation.RegressionMetrics;
import com.alibaba.alink.operator.common.evaluation.TuningRegressionMetric;
import com.alibaba.alink.operator.stream.evaluation.EvalMultiClassStreamOp;
import com.alibaba.alink.params.shared.linear.LinearTrainParams;
import com.alibaba.alink.pipeline.PipelineModel;
import com.alibaba.alink.pipeline.classification.KnnClassifier;
import com.alibaba.alink.pipeline.classification.LogisticRegression;
import com.alibaba.alink.pipeline.classification.RandomForestClassifier;
import com.alibaba.alink.pipeline.regression.LassoRegression;
import com.alibaba.alink.pipeline.regression.LinearRegression;
import com.alibaba.alink.pipeline.tuning.*;

public class Test1 {
    public static void main(String[] args) throws Exception {

        // 1.读取附件中的数据源，自定义划分训练集和测试集（3分）
        BatchOperator.setParallelism(1);
        String schemaStr="f1 double,f2 double,f3 double,f4 double,f5 double,label int";

        CsvSourceBatchOp csv=new CsvSourceBatchOp()
                .setFilePath("datafile/股票客户流失.csv")
                .setSchemaStr(schemaStr)
                .setIgnoreFirstLine(true)
                .setFieldDelimiter(",");


        BatchOperator<?> tranData=new SplitBatchOp().setFraction(0.8).linkFrom(csv);
        BatchOperator<?> testData=tranData.getSideOutput(0);

        System.out.println("testData.count() = " + testData.count());
        System.out.println("tranData.count() = " + tranData.count());

        // 2、自主选择使用Alink中至少两种算法构建模型，并设定初始值


        //特征列
        String [] features=new String[]{"f1","f2","f3","f4","f5"};
        //目标值
        String label="label";
        // KNN
        KnnClassifier knn = new KnnClassifier()
                .setFeatureCols(features)
                .setPredictionCol("pred")
                .setPredictionDetailCol("pred_detail")
                .setLabelCol(label)
                .setK(3);
        knn.fit(tranData).transform(testData).print();

        // 逻辑回归
        LogisticRegression lr = new LogisticRegression()
                .setFeatureCols(features)
                .setLabelCol(label)
                .setPredictionDetailCol("pred_detail")
                .setL1(0.1)
                .setMaxIter(100)
                .setPredictionCol("pred");
        lr.fit(tranData).transform(testData).print();

        // 3、对以上算法参数进行调优，可以打印中间调优结果
        // 对KNN调优
        ParamGrid paramGrid = new ParamGrid()
                .addGrid(knn, KnnClassifier.K, new Integer[] {1, 3, 5})
                .addGrid(knn, KnnClassifier.NUM_THREADS, new Integer[] {50, 100});
        MultiClassClassificationTuningEvaluator tuningEvaluator = new MultiClassClassificationTuningEvaluator()
                .setLabelCol(label)
                .setPredictionDetailCol("pred_detail")
                .setTuningMultiClassMetric("ACCURACY");

        GridSearchCV cv = new GridSearchCV()
                .setEstimator(knn)
                .setParamGrid(paramGrid)
                .setTuningEvaluator(tuningEvaluator)
                .setNumFolds(2)
                .enableLazyPrintTrainInfo("TrainInfo");
        GridSearchCVModel model = cv.fit(tranData);
        PipelineModel bestPipelineModel = model.getBestPipelineModel();
        BatchOperator<?> result1 = bestPipelineModel.transform(testData);


        // 逻辑回归
        ParamGrid paramGrid1 = new ParamGrid()
                .addGrid(lr, LogisticRegression.L_1, new Double[] {0.1, 0.3, 0.5})
                .addGrid(lr, LogisticRegression.NUM_THREADS, new Integer[] {50, 100});
        GridSearchCV cv1 = new GridSearchCV()
                .setEstimator(lr)
                .setParamGrid(paramGrid1)
                .setTuningEvaluator(tuningEvaluator)
                .setNumFolds(2)
                .enableLazyPrintTrainInfo("TrainInfo");
        GridSearchCVModel model1 = cv1.fit(tranData);
        PipelineModel bestPipelineModel1 = model1.getBestPipelineModel();
        BatchOperator<?> result2 = bestPipelineModel1.transform(testData);

        //(4)自主选择Alink至少两种指标进行模型评估（3分）

        MultiClassMetrics metrics = new EvalMultiClassBatchOp().setLabelCol(label).setPredictionDetailCol(
                "pred_detail").linkFrom(result1).collectMetrics();

        MultiClassMetrics metrics2 = new EvalMultiClassBatchOp().setLabelCol(label).setPredictionDetailCol(
                "pred_detail").linkFrom(result2).collectMetrics();

        if (metrics.getAccuracy() > metrics2.getAccuracy()){
            System.out.println("knn好");
        }else{
            System.out.println("逻辑回归好");
        }

        if (metrics.getMicroRecall() > metrics2.getMicroRecall()){
            System.out.println("knn好");
        }else{
            System.out.println("逻辑回归好");
        }
    }
}
